///////////////////////////////////////////////////////////////////////////////
// File:        Log.cc
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <string>
#include "Log.hpp"
#include "Console.hpp"

#if defined(__WINDOWS__)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#pragma warning(disable:4996)
#endif

///////////////////////////////////////////////////////////////////////////////
Log gLog;

///////////////////////////////////////////////////////////////////////////////
#if defined(__WINDOWS__)
typedef DWORD   TID_T;
#endif

static TID_T GetTID(void)
{
#if defined(__WINDOWS__)
    return ::GetCurrentThreadId();
#endif
}

static std::string GetTime(void)
{
    return std::string("NOW");
}
///////////////////////////////////////////////////////////////////////////////

static void PrintLog(FILE* fp, const char* level, const char* log)
{
    char buff[0x4000];
    sprintf(buff, "%s, %s, %lu, %s\n", GetTime().c_str(), level, GetTID(), log);
    printf("%s", buff);
    fwrite(buff, strlen(buff), 1, fp);
    fflush(fp);
}

///////////////////////////////////////////////////////////////////////////////
Log::Log(void)
    : ifp_(fopen("log/realmd.info", "w"))
    , bfp_(fopen("log/realmd.basic", "w"))
    , efp_(fopen("log/realmd.error", "w"))
    , dfp_(fopen("log/realmd.debug", "w"))
{
    assert(ifp_ && bfp_ && efp_ && dfp_);
}

Log::~Log(void)
{
    fclose(ifp_);
    fclose(bfp_);
    fclose(efp_);
    fclose(dfp_);
}

///////////////////////////////////////////////////////////////////////////////
void Log::Info(const char* fmt, ...)
{
    char buff[0x2000];
    va_list varg;
    va_start(varg, fmt);
    vsnprintf(buff, sizeof(buff), fmt, varg);
    va_end(varg);
    PrintLog(ifp_, "INFO", buff);
}

void Log::Basic(const char* fmt, ...)
{
    char buff[0x2000];
    va_list varg;
    va_start(varg, fmt);
    vsnprintf(buff, sizeof(buff), fmt, varg);
    va_end(varg);
    PrintLog(bfp_, "BASIC", buff);
}

void Log::Error(const char* fmt, ...)
{
    char buff[0x2000];
    va_list varg;
    va_start(varg, fmt);
    vsnprintf(buff, sizeof(buff), fmt, varg);
    va_end(varg);
    Console::SetColors(
        Console::foreground_RED | Console::foreground_INTENSITY, 
        Console::background_BLACK);
    PrintLog(efp_, "ERROR", buff);
    Console::SetDefaultColors();
}

void Log::Debug(const char* fmt, ...)
{
    char buff[0x2000];
    va_list varg;
    va_start(varg, fmt);
    vsnprintf(buff, sizeof(buff), fmt, varg);
    va_end(varg);
    Console::SetColors(
        Console::foreground_GREEN | Console::foreground_INTENSITY, 
        Console::background_BLACK);
    PrintLog(dfp_, "DEBUG", buff);
    Console::SetDefaultColors();
}